Skip to content

Add semantic/episodic/procedural memory layering to managed-memory skill#244

Open
jennsun wants to merge 4 commits into
databricks:mainfrom
jennsun:managed-memory-layers
Open

Add semantic/episodic/procedural memory layering to managed-memory skill#244
jennsun wants to merge 4 commits into
databricks:mainfrom
jennsun:managed-memory-layers

Conversation

@jennsun

@jennsun jennsun commented Jun 30, 2026

Copy link
Copy Markdown
Contributor

Summary

Adds an optional layered-memory convention on top of the flat managed-memory store, so an agent can organize what it remembers into semantic / episodic / procedural layers.

The base skill stores entries at flat /memories/... paths with no notion of memory type. This PR adds a convention (prompt + path prefixes — no new tools, grants, or code) that has the agent distill each memory into one of three kinds and store it under a matching /memories/<layer>/ prefix.

What changed

  • SKILL.md — new "Step 6 (optional) — Layered memory" section:
    • Layer table mapping semantic → /memories/semantic/..., procedural → /memories/procedural/..., episodic → Conversations API + /memories/episodic/... (every path still starts /memories/ per the API).
    • Episodic via the Conversations APIDatabricksOpenAIconversations.create(...)responses.create(conversation=...), reusing the same resolve_scope() scope as the five tools. Honestly scoped to the Supervisor API path (not the in-process Agents SDK / LangGraph loop), with guidance for the loop case.
    • Pointers added from Step 5 and the Notes; new trigger keywords in frontmatter.
  • memory-layers.md — new companion file: layer definitions, a "decide the layer before you save" procedure, path-prefix examples, and a drop-in layered MEMORY_INSTRUCTIONS.
  • Step 2 fix (USE_CATALOG / USE_SCHEMA): grant the deployed app SP USE_CATALOG on the catalog and USE_SCHEMA on the schema, plus a troubleshooting row. READ/WRITE_MEMORY_STORE alone is insufficient — UC needs the parent traversal privileges or every entries call fails with User does not have USE CATALOG. Found during end-to-end testing below.
  • Synced to all conversational templates via sync-skills.py.

End-to-end testing

Validated the layering against a live Databricks app (LangGraph base template + the five memory tools + the layered MEMORY_INSTRUCTIONS from memory-layers.md, model databricks-claude-sonnet-4), on a staging workspace.

Setup: created a new UC memory store jenny.default.layered_memory_test and deployed a new app agent-memory-layers.

I gave the agent facts of each kind and confirmed via direct REST reads that they landed under the right path prefixes:

Layer Input Stored path (verified via REST)
Semantic "I prefer TypeScript, 2-space indent" / "commit msgs imperative, 50-char" /memories/semantic/coding-preferences.md · /memories/semantic/commit-message-style.md
Procedural PR-review steps / deploy checklist /memories/procedural/pr-review-process.md · /memories/procedural/deploy-checklist.md
Episodic "on 2026-06-30 we standardized on pnpm" / "on 2026-06-28 migrated staging DB to Lakebase" /memories/episodic/pnpm-standardization-decision.md · /memories/episodic/staging-database-migration.md

Results:

  • Layer classification — the agent distilled each fact into the correct layer and prefix, unprompted beyond the system instructions.
  • Recall — in fresh conversations the agent ran list_memoriesget_memory and answered correctly from each layer.
  • Per-user isolation — a different user scope saw none of the stored memories.
  • Local + deployed — verified both via start-app --no-ui (scope faked with X-Forwarded-User) and the deployed app (scope resolved from the OBO token to the real user id).

The deployed app initially failed with User does not have USE CATALOG on Catalog 'jenny'; granting the SP USE_CATALOG + USE_SCHEMA fixed it immediately — which is the Step 2 change included here.

🤖 Generated with Claude Code

Episodic memory via a store-backed conversation (Beta) — verified working

The first draft of this section was wrong (responses.create(conversation=<id>) is rejected by the staging gateway with 400 "conversation: Extra inputs are not permitted"). Corrected to the integration that actually works, verified end-to-end on staging (databricks-openai 0.17.0, openai-agents 0.17.7):

  • Back the OpenAI Agents SDK session with the memory store instead of Lakebase — create a conversation bound to {memory_store, scope}, wrap it in OpenAIConversationsSession, pass it as session= to Runner.run.
  • The session reads/writes turns via conversations.items.list/create (supported), using one AsyncDatabricksOpenAI(use_ai_gateway=True) client + set_default_openai_api("responses").
  • This replaces the AsyncDatabricksSession (Lakebase) block in agent-openai-advanced/agent_server/agent.py.

Test: stated a codeword in turn 1; recalled correctly in turn 2, and again from a fresh session object with the same conversation id (proves cross-request persistence in the store). Still flagged Beta since the Conversations APIs are beta.

Adds an optional layered-memory convention on top of the flat memory
store: distill each memory into semantic / episodic / procedural and
store under a matching /memories/<layer>/ path prefix.

- SKILL.md: new "Step 6 — Layered memory" section with the layer table,
  path conventions, and the Conversations API flow for episodic state
  (binds a conversation to the store + scope via DatabricksOpenAI,
  scoped to the Supervisor API path); pointers from Step 5 and Notes;
  new trigger keywords in frontmatter.
- memory-layers.md: companion guide with layer definitions, a
  "decide the layer before you save" procedure, path-prefix examples,
  and a drop-in layered MEMORY_INSTRUCTIONS.
- Synced to all conversational templates via sync-skills.py.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@jennsun
jennsun force-pushed the managed-memory-layers branch from c21cc9c to 17a8407 Compare June 30, 2026 23:23
READ/WRITE_MEMORY_STORE alone is insufficient for a deployed app: UC
requires USE_CATALOG on the catalog and USE_SCHEMA on the schema to
traverse to the memory-store securable, or every entries call fails with
"User does not have USE CATALOG on Catalog '<catalog>'". The store owner
already holds these (so local testing as the owner doesn't hit it), but
the deployed app service principal almost always needs them.

- Step 2: add the two parent-grant PATCH calls for the SP.
- Troubleshooting: add a row for the USE CATALOG error.
- Synced to all conversational templates.

Found while end-to-end testing the layered-memory skill on a deployed
Databricks app.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
-H "Authorization: Bearer $TOKEN" -H "Content-Type: application/json" \
-d "{\"changes\":[{\"principal\":\"$APP_SP\",\"add\":[\"USE_SCHEMA\"]}]}"
```

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

adding this from test run

@jennsun
jennsun requested a review from annzhang-db June 30, 2026 23:52
jennsun and others added 2 commits July 2, 2026 14:32
Tested the Conversations API episodic flow on a staging workspace
(databricks-openai 0.17.0, use_ai_gateway=True):

- conversations.create({memory_store, scope}) works; the conversation is
  created and retrievable.
- conversations.items.create / .list work; turn state persists and reads
  back.
- BUT responses.create(conversation=<id>) is rejected server-side with
  400 "conversation: Extra inputs are not permitted" (both top-level and
  in extra_body), while a plain responses.create works. So the documented
  end-to-end flow is not live on every workspace's AI Gateway yet.
- Conversation state is separate from memory-store entries (the .../entries
  list API does not surface it).

Add a Beta / availability-varies callout with the exact error and a
fallback, so users verify on their workspace instead of assuming it works.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
The previous instructions were wrong: responses.create(conversation=<id>)
is rejected by some gateways with 400 "conversation: Extra inputs are not
permitted". The correct integration for the OpenAI Agents SDK templates is
to back the short-term session with the memory store:

- create a conversation bound to {memory_store, scope}
- wrap it in the Agents SDK OpenAIConversationsSession
- pass it as session= to Runner.run (replaces the Lakebase
  AsyncDatabricksSession block in agent-openai-advanced)

The session reads/writes turns via conversations.items.list/create (the
supported surface), using one AsyncDatabricksOpenAI(use_ai_gateway=True)
client and set_default_openai_api("responses"). Verified end-to-end on
staging (databricks-openai 0.17.0, openai-agents 0.17.7): recall works
across separate requests and a fresh session with the same conversation id.

Still marked Beta (Conversations APIs are beta). Synced to all templates.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant